package com.wyd.component.netty.manager;

import com.alibaba.fastjson.JSON;
import com.wyd.component.netty.constants.ChannelKey;
import com.wyd.component.netty.constants.Constants;
import com.wyd.component.netty.message.*;
import com.wyd.exception.GlobalErrorCodeConstants;
import com.wyd.common.Result;
import com.wyd.redis.RedisUtils;
import com.wyd.utils.DateUtils;
import io.netty.channel.Channel;
import io.netty.util.Attribute;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.*;

@Component
@Slf4j
public class ChannelManager {

    private static ExecutorService threadPoolExecutor = new ThreadPoolExecutor(2, 5, 60L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<Runnable>(200), new ThreadPoolExecutor.CallerRunsPolicy());

    private static ChannelManager channelManager = new ChannelManager();

    @Resource
    RedisUtils redisUtils;

    @PostConstruct
    public void init() {
        channelManager.redisUtils = this.redisUtils;
    }

    private static Map<String, Channel> channelMap = new ConcurrentHashMap<>();

    public static synchronized boolean addChannel(Channel channel) {
        Attribute<ChannelKey> attr = channel.attr(Constants.attriKey);
        ChannelKey channelKey = attr.get();
        removeChannel(channelKey.getCardId());
        channelMap.put(channelKey.getCardId(), channel);

        return true;
    }


    public static synchronized void removeChannel(String cardId) {
        if (cardId != null) {
            Channel remove = channelMap.remove(cardId);
            if (remove != null) {
                closeChannel(remove);
            }
        }
    }

    private static void closeChannel(Channel channel) {
        try {
            channel.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void handleChannelMsg(Channel channel, DeviceBaseMessage msg) {
        log.info("当前已登录：{}", JSON.toJSONString(channelMap));
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                log.info("获取消息：{}", msg.toString());
                String cardId = msg.getCardId();
                Attribute<ChannelKey> attr = channel.attr(Constants.attriKey);
                ChannelKey channelKey = attr.get();

                if (channelKey == null) {
                    if (msg instanceof LoginReq) {
                        log.info("handleChannelMsg -> LoginReq");
                        LoginReq loginReq = (LoginReq) msg;
                        LoginResp loginResp = new LoginResp();
                        loginResp.setCardId(loginReq.getCardId());
                        loginResp.setSeqId(loginReq.getSeqId());
                        loginResp.setCreateTime(DateUtils.nowDate());
                        loginResp.setLoginResult(true);
                        channelKey = new ChannelKey();
                        channelKey.setCardId(loginReq.getCardId());
                        channelKey.setConnTime(DateUtils.nowLdt());
                        channelKey.setUserName(loginReq.getUserName());
                        channelKey.setPassWord(loginReq.getPassWord());
                        channel.attr(Constants.attriKey).set(channelKey);

                        //存入redis 5分钟
                        channelManager.redisUtils.set(Constants.DEVICE_NODE+channelKey.getCardId(),JSON.toJSONString(loginResp),300);

                        addChannel(channel);

                        channel.writeAndFlush(loginResp);
                        log.info("handleChannelMsg -> writeAndFlush success");
                    } else {
                        channel.close();
                        log.info("handleChannelMsg -> writeAndFlush close");
                    }
                } else {
                    log.info("handleChannelMsg -> channelKey == null");
                    if (!channelKey.getCardId().equals(cardId)) {
                        closeChannel(channel);
                        log.error("ChannelKey与消息不一致{}<>{}", channelKey.getCardId(), cardId);
                        return;
                    }
                    if (msg instanceof HeartBeatReq) {
                        /**********************保存eartBeatResp***********/
                        HeartBeatReq heartBeatReq = (HeartBeatReq) msg;
                        HeartBeatResp heartBeatResp = new HeartBeatResp();
                        heartBeatResp.setCardId(heartBeatReq.getCardId());
                        heartBeatResp.setSeqId(heartBeatReq.getSeqId());
                        heartBeatResp.setCreateTime(DateUtils.nowDate());
                        channel.writeAndFlush(heartBeatResp);

                    }
                }
            }
        });
    }


    public static Result sendMsg(DeviceBaseMessage baseMessage) {
        Channel channel = channelMap.get(baseMessage.getCardId());
        if (channel != null) {
            channel.writeAndFlush(baseMessage);
            return Result.success("命令下发成功");
        }
        return Result.error(GlobalErrorCodeConstants.NOT_ONLINE.getCode(),GlobalErrorCodeConstants.NOT_ONLINE.getMsg());
    }

    public static void main(String[] args) {
        //登录：{"cardId":"340000852","createTime":1653124058000,"passWord":"xiaojing","seqId":"05201531434535000001","type":"LOGIN_REQ","userName":"xiaojing"}
        //心跳：{"cardId":"340000852","createTime":1653124060000,"seqId":"05211421293735900179","type":"HEART_BEAT_RESP"}
        //心跳：{"cardId":"340000852","createTime":1653124178000,"seqId":"05211421293735900179","type":"HEART_BEAT_REQ"}
    }

}
